/*================================================================
*   Copyright (C) 2020 Sangfor Ltd. All rights reserved.
*   
*   文件名称：test.cpp
*   创 建 者：Ann
*   创建日期：2020年05月24日
*   描    述：
*
================================================================*/

#include <stdio.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <errno.h>
#include <fcntl.h>
#include <string>

int main()
{
    //设置文件描述符为非阻塞方式
    int flag = fcntl(0, F_GETFL);
    printf("flag : %d\n", flag);
    fcntl(0, F_SETFL, flag | O_NONBLOCK);

    //1.创建epoll操作句柄
    int epollfd = epoll_create(1);
    if(epollfd < 0)
    {
        perror("epoll_createc");
        return 0;
    }
    //2.添加描述符到epoll当中去
    //  2.1 定义epoll事件结构
    struct epoll_event ev;
    //采用的是epoll的et模式
    ev.events = EPOLLIN | EPOLLET; 
    ev.data.fd = 0;

    epoll_ctl(epollfd, EPOLL_CTL_ADD, 0, &ev);
    //3.监控
    while(1)
    {
        struct epoll_event evs[10];
        int ret = epoll_wait(epollfd, evs, 10, -1);
        if(ret < 0)
        {
            perror("epoll_wait");
            continue;
        }

        for(int i = 0; i < ret; i++)
        {
            if(evs[i].data.fd == 0)
            {
                std::string read_date;
                while(1)
                {
                    char buf[5] = {0};
                    //如果read在读取数据的时候，没有更改文件描述符的默认阻塞方式，则接收缓冲区当中没有数据的时候，read会阻塞
                    //在使用epoll et模式的时候，通常都是将描述符设置为非阻塞模式
                    //  好处：
                    //      当描述符为非阻塞模式的时候，即使接收缓冲区当中没有数据，也不会阻塞该执行流
                    ssize_t readsize = read(evs[i].data.fd, buf, sizeof(buf) - 1);
                    if(readsize < 0)
                    {
                        if(errno == EAGAIN || errno == EWOULDBLOCK)
                        {
                            goto myend;
                        }
                        perror("read");
                        return 0;
                    }

                    read_date += buf;
myend:
                    if(readsize < (ssize_t)sizeof(buf) - 1)
                    {
                        printf("read_date = %s\n", read_date.c_str());
                        break;
                    }
                }
            }
        }
    }
    return 0;
}
